/*
** msgbox.c
**
** Pictor, Version 1.51, Copyright (c) 1992-94 SoftCircuits
** Redistributed by permission.
*/

#include <stdio.h>
#include <ctype.h>
#include "pictor.h"

#ifdef MOUSE_SUPPORT
	#include "mouse.h"
#endif


static struct {
	int numitems;
	char *items[3];
} buttons[] = {
	{ 1,{"    ~OK    ", NULL,NULL}, },
	{ 2,{"    ~OK    ", "   ~Cancel   ",NULL}, },
	{ 2,{"   ~Retry   ","   ~Cancel   ",NULL}, },
	{ 2,{"   ~Retry   ","   ~Abort   ", NULL}, },
	{ 2,{"   ~Yes   ",  "    ~No    ",NULL}, },
	{ 3,{"   ~Yes   ",  "    ~No    ","   ~Cancel   "}, },
};

#define MAX_LINES 15
static int linelen[MAX_LINES];      /* length of each line */

/*
** Displays a message box. If the user presses Enter, it returns a
** value indicating which selection was made. 0 indicates the right-most
** selection, 1 indicates the second-to-right selection, and so on. If
** flags == MB_OK the return value is always 0.
**
** 0 is returned if Escape is pressed. Use the escpressed() macro to
** determine if 0 was returned because Escape was pressed or the
** right-most item was selected.
**
** NOTE: This function can be called recursively if it is active and:
** 1) a critical error occurs, 2) help is selected.
**
** WARNING: This function gets called from the critical-error
** interrupt handler. The handler safely disables help and
** this function calls wopen with the WO_STATICMEM attribute.
** If you modify this function, don't call any routine that,
** in-turn, calls malloc.
*/
int messagebox(char *msg,char *title,int flags,COLORSTRUCT *colors)
{
	char buffer[255] = {'\0'};
	int i,j,key,buttonwidth,top,left,width,height;
	int selection = 0,done = FALSE,update = TRUE;
	int maxlen = 0,currlen = 0;
	int numlines = 0;
	
	#ifdef MOUSE_SUPPORT
		int mousex, mousey, currentmousebutton = NO_BUTTON_PRESSED, 
			prevmousebutton = NO_BUTTON_PRESSED, buttoncolstart, buttoncolend, mousecolumn;
	#endif

	/* determine number of lines and */
	/* length of the longest line */
	for(i = 0;msg[i] != '\0';i++) {
		if(msg[i] == '\n') {
			/* test for too many lines */
			if((numlines + 1) >= MAX_LINES)
				break;

			linelen[numlines] = currlen;
			numlines++;
			currlen = 0;
		}
		else currlen++;

		if(currlen > maxlen)
			maxlen = currlen;
	}
	/* count last line */
	linelen[numlines] = currlen;
	numlines++;

	/* get width of all buttons side-by-side */
	for(buttonwidth = 0,i = 0;i < buttons[flags].numitems;i++)
		buttonwidth += hstrlen(buttons[flags].items[i]);

	/* calculate window coordinates */
	height = numlines + 4;
	width = ((maxlen > buttonwidth) ? maxlen : buttonwidth) + 4;
	top = center(height + 2,_PL_rows);
	left = center(width + 2,_PL_columns);

	#ifdef MOUSE_SUPPORT
		if(_PL_mousepresent)
		{
			hidemouse();
		}
	#endif
		
	wopen(top,left,height + 2,width + 2,colors->normal,
		WO_STATICMEM | WO_SHADOW);
	wtitle(title);
	
	#ifdef MOUSE_SUPPORT
		if(_PL_mousepresent)
		{
			hidemouse();
		}	
	#endif

	/* display message text */
	for(i = 0,j = 0;i < numlines;i++,j++) {
		setwpos(i + 2,center(linelen[i],width));
		while(msg[j] != '\0' && msg[j] != '\n')
			wputc(msg[j++]);
	}

	while(!done) {
		if(update) {
			#ifdef MOUSE_SUPPORT
				if(_PL_mousepresent)
				{
					hidemouse();
				}
			#endif
			
			setvpos((top + height) - 1,left + center(buttonwidth,width));
			for(i = 0;i < buttons[flags].numitems;i++) {
				if(i == selection) {
					vcolor(colors->select);
					hputs(buttons[flags].items[i],colors->boldselect);
				}
				else {
					vcolor(colors->normal);
					hputs(buttons[flags].items[i],colors->boldnormal);
				}
			}
			update = FALSE;
			
			#ifdef MOUSE_SUPPORT
				if(_PL_mousepresent)
				{
					showmouse();
				}
			#endif
		}
		
		#ifdef MOUSE_SUPPORT
			if(_PL_mousepresent)
			{
				//buttonrow = 
				//buttonlength = 
				mousestatus(&mousex, &mousey, &currentmousebutton);
				//switch(currentmousebutton)
				if(currentmousebutton == LEFT_BUTTON_PRESSED)
				{
					setvpos(3, 1);
					sprintf(buffer, "Checking mouse position...");
					vputs(buffer); 
					
					/* Assume user cannot move mouse in time it takes to
					 * check buttons. */
					if(mousetoPLrows(mousey) == (top + height) - 1)
					{
						/* Center calculates the position of where the video
						 * cursor should start. This can also be used to
						 * mouse detection. */
						
						/* Start checking for the cursor's location in the
						 * row. The following variables are pre-calculated to save time. */
						mousecolumn = mousetoPLcolumns(mousex);  
						buttoncolstart = left + center(buttonwidth,width);
						buttoncolend = buttoncolstart;
						
						/* O(n) time- make it faster? BDD? */
						for(i = 0; i < buttons[flags].numitems; i++)
						{
							buttoncolend += hstrlen(buttons[flags].items[i]);
							if(mousecolumn >= buttoncolstart && mousecolumn < buttoncolend)
							{
								selection = i;
								update = TRUE;
								break;
							}
							buttoncolstart = buttoncolend;
						}
					}
				}
				else if(currentmousebutton == NO_BUTTON_PRESSED && prevmousebutton == LEFT_BUTTON_PRESSED)
				{
					if(mousetoPLrows(mousey) == (top + height) - 1)
					{
						mousecolumn = mousetoPLcolumns(mousex);  
						buttoncolstart = left + center(buttonwidth,width);
						buttoncolend = buttoncolstart;
						
						/* O(n) time- make it faster? BDD? */
						for(i = 0; i < buttons[flags].numitems; i++)
						{
							buttoncolend += hstrlen(buttons[flags].items[i]);
							if(mousecolumn >= buttoncolstart && mousecolumn < buttoncolend)
							{
								selection = i;
								done = TRUE;
								break;
							}
							buttoncolstart = buttoncolend;
						}

					}
				}
				prevmousebutton = currentmousebutton;
				if(!querykeyboard())
				{
					continue;
				}
			}
			
			/* This whole body of code above really needs to be optimized
			 * at some point- W. Jones. */
			
		#endif

		switch(key = kbdread()) {
			case LEFT_KEY:
				if(buttons[flags].numitems == 1) {
					beep();
				}
				else {
					if(selection > 0)
						selection--;
					else
						selection = (buttons[flags].numitems - 1);
					update = TRUE;
				}
				break;
			case RIGHT_KEY:
			case SPACE_BAR:
				if(buttons[flags].numitems == 1) {
					beep();
				}
				else {
					if(selection < (buttons[flags].numitems - 1))
						selection++;
					else
						selection = 0;
					update = TRUE;
				}
				break;
			case ENTER_KEY:
				done = TRUE;
				break;
			case ESCAPE_KEY:
				selection = (buttons[flags].numitems - 1);
				done = TRUE;
				break;
			case F1_KEY:
				if(_PL_helpfunc != NULL)
					_PL_helpfunc(_PL_helpcontext);
				else beep();
				break;
			default: 	/* check for hot-key */
				key &= 0xFF;
				if(isalnum(key)) {
					key = tolower(key);
					for(i = 0;i < buttons[flags].numitems;i++) {
						if(key == tolower(gethotkey(buttons[flags].items[i]))) {
							selection = i;
							done = TRUE;
							break;
						}
					}
				}
				if(!done) beep();
				break;
		}
	}
	#ifdef MOUSE_SUPPORT
		if(_PL_mousepresent)
		{
			hidemouse();
		}
	#endif
		
		wclose();
	
	#ifdef MOUSE_SUPPORT
		if(_PL_mousepresent)
		{
			showmouse();
		}
	#endif
	
	

	return((buttons[flags].numitems - 1) -	selection);

} /* messagebox */
